# -*- coding: utf-8 -*-
# #####################################################################
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2011 OpenERP s.a. (<http://openerp.com>).
# Copyright (C) 2013 INIT Tech Co., Ltd (http://init.vn).
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
######################################################################
from datetime import datetime, timedelta
from dateutil.relativedelta import relativedelta
import time

from osv import fields, osv
from tools.translate import _
import decimal_precision as dp
import netsvc


class init_multi_mrp(osv.osv):
    _name = 'init.multi.mrp'

    _columns = {
        'name': fields.char('Sequence', size=64, readonly=True, select=True),
        'employee_id': fields.many2one('hr.employee', 'Employee', required=True,
                                       readonly=True, states={'draft': [('readonly', False)]}),
        'date': fields.date('Date', required=True,
                            readonly=True, states={'draft': [('readonly', False)]}),
        'detail_ids': fields.one2many('init.multi.mrp.detail', 'detail_id', 'Detail Multi MRP',
                                      readonly=True, states={'draft': [('readonly', False)]}),
        'location_id': fields.many2one('stock.location', 'Location', required=True,
                                       readonly=True, states={'draft': [('readonly', False)]}),
        'state': fields.selection([('draft', 'Draft'), ('confirm', 'Confirm'), ('produce', 'Produce'), ('done', 'Done'),
                                   ('cancel', 'Cancel')], 'Status', readonly=True),
        'product_id': fields.related('detail_ids', 'product_id', type='many2one', relation='product.product',
                                     string='Product'),
        'categ_id': fields.related('detail_ids', 'categ_id', type='many2one', relation='product.category',
                                   string='Category'),
    }

    def button_confirm(self, cr, uid, ids, context=None):
        for obj in self.browse(cr, uid, ids):
            for line in obj.detail_ids:
                prodlot_id = self.pool.get('stock.production.lot').create(cr, uid, {
                    'name': line.prodlot_no,
                    'product_id': line.product_id.id
                }, context=context)
                line.write({'prodlot_id': prodlot_id})
        return self.write(cr, uid, ids, {'state': 'confirm'})

    def action_compute(self, cr, uid, ids, properties=[]):
        results = []
        bom_obj = self.pool.get('mrp.bom')
        mrp_detail_obj = self.pool.get('init.multi.mrp.detail')
        for detail in mrp_detail_obj.browse(cr, uid, ids):
            bom_point = detail.bom_id
            bom_id = detail.bom_id.id
            if not bom_point:
                bom_id = bom_obj._bom_find(cr, uid, detail.product_id.id, detail.product_uom.id, properties)
                if bom_id:
                    bom_point = bom_obj.browse(cr, uid, bom_id)
                    mrp_detail_obj.write(cr, uid, [detail.id], {'bom_id': bom_id})
            if not bom_id:
                raise osv.except_osv(_('Error'), _("Couldn't find bill of material for product"))

            factor = detail.quantity * detail.product_uom.factor_inv / bom_point.product_uom.factor
            res = bom_obj._bom_explode(cr, uid, bom_point, factor / bom_point.product_qty, properties)
            results = res[0]
        return results

    def button_produce(self, cr, uid, ids, context=None):
        multi = self.browse(cr, uid, ids)[0]
        obj_detail_ids = multi.detail_ids
        picking_ids = []
        picking_in_id = False
        picking_out_id = False
        seq_obj = self.pool.get('ir.sequence')
        pick_obj = self.pool.get('stock.picking')
        move_obj = self.pool.get('stock.move')
        wf_service = netsvc.LocalService("workflow")

        for detail in obj_detail_ids:
            routing_loc = None
            pick_type = 'internal'
            address_id = False
            if detail.bom_id.routing_id and detail.bom_id.routing_id.location_id:
                routing_loc = detail.bom_id.routing_id.location_id
                if routing_loc.usage <> 'internal':
                    pick_type = 'out'
                address_id = routing_loc.address_id and routing_loc.address_id.id or False
                routing_loc = routing_loc.id
            if not picking_out_id:
                pick_name = seq_obj.get(cr, uid, 'stock.picking.' + pick_type)
                picking_out_id = pick_obj.create(cr, uid, {
                    'name': pick_name,
                    'origin': 'OUT: %s' % multi.name,
                    'type': pick_type,
                    'move_type': 'one',
                    'state': 'draft',
                    'address_id': address_id,
                    'auto_picking': True,
                    'multi_id': multi.id,
                })
                picking_ids.append(picking_out_id)

            if not picking_in_id:
                pick_name = seq_obj.get(cr, uid, 'stock.picking.' + pick_type)
                picking_in_id = pick_obj.create(cr, uid, {
                    'name': pick_name,
                    'origin': 'IN: %s' % multi.name,
                    'type': pick_type,
                    'move_type': 'one',
                    'address_id': address_id,
                    'state': 'draft',
                    'multi_id': multi.id,
                })
                picking_ids.append(picking_in_id)
            source = detail.product_id.product_tmpl_id.property_stock_production.id
            data = {
                'name': 'PROD:' + detail.product_id.name,
                'date': multi.date,
                'picking_id': picking_in_id,
                'product_id': detail.product_id.id,
                'product_qty': detail.quantity,
                'product_uom': detail.product_uom.id,
                'product_uos_qty': detail.quantity,
                'product_uos': detail.product_uom.id,
                'prodlot_id': detail.prodlot_id and detail.prodlot_id.id or False,
                'location_id': source,
                'location_dest_id': multi.location_id.id,
                'state': 'draft',
            }
            res_final_id = move_obj.create(cr, uid, data)

            for line in self.action_compute(cr, uid, [detail.id], context):
                newdate = multi.date
                product_obj = self.pool.get('product.product').browse(cr, uid, line['product_id'])
                if product_obj.type in ('product', 'consu'):
                    res_dest_id = move_obj.create(cr, uid, {
                        'name': 'PROD:' + line['name'],
                        'date': newdate,
                        'picking_id': picking_out_id,
                        'product_id': line['product_id'],
                        'product_qty': line['product_qty'],
                        'product_uom': line['product_uom'],
                        'product_uos_qty': line['product_qty'],
                        'product_uos': line['product_uom'],
                        'location_id': routing_loc or multi.location_id.id,
                        'location_dest_id': source,
                        'move_dest_id': res_final_id,
                        'state': 'draft',
                    })
                    move_obj.action_consume(cr, uid, [res_dest_id], line['product_qty'], context=context)
            wf_service.trg_validate(uid, 'stock.picking', picking_out_id, 'button_confirm', cr)
            self.pool.get('stock.picking').action_move(cr, uid, [picking_out_id], context=context)
            wf_service.trg_validate(uid, 'stock.picking', picking_out_id, 'button_done', cr)
            ####cua quan ne
            pick_obj.draft_force_assign(cr, uid, [picking_in_id])
            pick_obj.force_assign(cr, uid, [picking_in_id])
            ####              

        self.write(cr, uid, ids, {'state': 'done'})
        return True

    def button_cancel(self, cr, uid, ids, context=None):
        picking_ids = self.pool.get('stock.picking').search(cr, uid, [('multi_id', 'in', ids)])
        picking_obj = self.pool.get('stock.picking').browse(cr, uid, picking_ids)
        for line in picking_obj:
            self.pool.get('stock.picking').write(cr, uid, line.id, {'state': 'draft'})
            for move in line.move_lines:
                self.pool.get('stock.move').write(cr, uid, move.id, {'state': 'draft'})
                self.pool.get('stock.move').unlink(cr, uid, [move.id])
            self.pool.get('stock.picking').unlink(cr, uid, [line.id])

        return self.write(cr, uid, ids, {'state': 'cancel'})

    _defaults = {
        'date': lambda *a: time.strftime('%Y-%m-%d'),
        'state': 'draft',
        'name': lambda self, cr, uid, context: self.pool.get('ir.sequence').get(cr, uid, 'init.multi.mrp'),
    }

    def copy(self, cr, uid, id, vals, context):
        vals['name'] = self.pool.get('ir.sequence').get(cr, uid, 'init.multi.mrp')
        return super(init_multi_mrp, self).copy(cr, uid, id, vals, context)


init_multi_mrp()


class init_multi_mrp_detail(osv.osv):
    _name = "init.multi.mrp.detail"
    _columns = {
        'product_id': fields.many2one('product.product', 'Product', required=True),
        #         'categ_id': fields.many2one('product.category', 'Category', domain="[('type','=','normal')]"),

        'categ_id': fields.related('product_id', 'categ_id', type='many2one',
                                   relation='product.category', string='Category',
                                   store={
                                       'init.multi.mrp.detail': (
                                       lambda self, cr, uid, ids, c={}: ids, ['product_id'], 20),
                                   }),
        'quantity': fields.float('Quantity'),
        'product_uom': fields.many2one('product.uom', 'UoM', required=True),
        'prodlot_id': fields.many2one('stock.production.lot', 'Production Lot'),
        'prodlot_no': fields.char('Production Lot', 64, required=True),
        'bom_id': fields.many2one('mrp.bom', 'BOM'),
        'detail_id': fields.many2one('init.multi.mrp', 'Multi MRP'),
        'employee_id': fields.related('detail_id', 'employee_id', string='Employee', type='many2one',
                                      relation='hr.employee', store=True),
        'date': fields.related('detail_id', 'date', string='Date', store=True, readonly=True, type="date")
    }

    def onchange_product_id(self, cr, uid, ids, product_id, context=None):
        if not product_id:
            return {}
        res = {}
        product = self.pool.get('product.product').browse(cr, uid, product_id, context=context)
        production_ids = self.pool.get('mrp.production').search(cr, uid, [('product_id', '=', product_id)])
        production_obj = production_ids and self.pool.get('mrp.production').browse(cr, uid, production_ids)[0] or False
        res['categ_id'] = product.categ_id and product.categ_id.id or False
        res['product_uom'] = product.uom_id and product.uom_id.id or False
        res['bom_id'] = production_obj and (production_obj.bom_id and production_obj.bom_id.id or False) or False
        return {'value': res}

    _defaults = {
    }


init_multi_mrp_detail()


class stock_picking(osv.osv):
    _inherit = 'stock.picking'
    _columns = {
        'multi_id': fields.many2one('init.multi.mrp', 'Multi'),
    }


stock_picking()


class mrp_production(osv.osv):
    _inherit = 'mrp.production'
    _columns = {
        'employee_id': fields.many2one('hr.employee', 'Employee'),
    }


mrp_production()
